#!/usr/bin/env python
###############################################################################
# Name: puzzle2py.py                                                          #
# Purpose: Convert a file of puzzle data to a python module                   #
# Author: Cody Precord <cprecord@editra.org>                                  #
# Copyright: (c) 2008 Cody Precord <staff@editra.org>                         #
# License: wxWindows License                                                  #
###############################################################################

""""
Puzzle2Py

Converts a file of puzzle data into a python module containing a single
dictionary of puzzle strings organized by difficulty level.

The puzzle data file must be organized as follows:

  1) Each section of puzzles must be started with a difficulty label
  2) Puzzles are a contigous string of 81 values (.123456789)

Difficulty lables are signified by a '#' (i.e. # Easy). The acceptible labels
are as follows (Easy, Normal, Hard, Evil).

Example:

# Easy
.94...13..............76..2.8..1.....32.........2...6.....5.4.......8..7..63.4..8

@summary: Convert a file of puzzle data to a python module

"""

__author__ = "Cody Precord <cprecord@editra.org>"
__revision__ = "$Revision$"
__scid__ = "$Id$"

#-----------------------------------------------------------------------------#
# Imports
import sys

#-----------------------------------------------------------------------------#
# Globals

DIFFICULTY_EASY   = 0
DIFFICULTY_NORMAL = 1
DIFFICULTY_HARD   = 2
DIFFICULTY_EVIL   = 3
DIFFICULTIES = { 'Easy' : DIFFICULTY_EASY,
                 'Normal' : DIFFICULTY_NORMAL,
                 'Hard' : DIFFICULTY_HARD,
                 'Evil' : DIFFICULTY_EVIL }

#-----------------------------------------------------------------------------#
# Functions

def MakePyString(pdict):
    """Make the dictionary into a string of python code
    @param pdict: {difficulty : [puzzle strings]}

    """
    rstring = "# Generated by puzzle2py.py\n"
    rstring += "PUZZLES = dict()\n"
    for diff, puzzles in pdict.iteritems():
        rstring += "PUZZLES[%s] = [\\\n" % diff
        for puzzle in puzzles:
            rstring += "\"%s\",\n" % puzzle
        rstring += "]\n\n"
    return rstring

def PrintHelp():
    """Print help message on how to use this script"""
    print "Puzzle2Py - Convert Puzzle Data to a Python Module"
    print "Type `puzzle2py datafile outfile.py`"

def ReadPuzzles(fname):
    """Load the game boards from a puzzle data file. The data file must
    contain puzzles that are in the standard compact form, with one puzzle
    per line. Puzzle difficultys can be specified by a line starting with
    '#' then followed by the difficutly i.e '# Normal'.
    
    The valid difficulties are (Easy, Normal, Hard, Evil)

    @keyword fname: path to file to load
    @return: boolean

    """
    puzzles = dict()
    current = None
    f_handle = open(fname, 'r')
    for line in f_handle:
        line = line.strip()
        if line.startswith("#"):
            current = line.lstrip("#").strip().title()
            current = DIFFICULTIES.get(current, None)
            if current is not None and not puzzles.has_key(current):
                puzzles[current] = list()
        elif current is not None and len(line) == 81:
            puzzles[current].append(line)
        else:
            pass
    f_handle.close()
    return puzzles

#-----------------------------------------------------------------------------#
# Main

if __name__ == '__main__':
    # Check Args
    if len(sys.argv) != 3:
        PrintHelp()
        sys.exit()

    # Read Input Data
    print "Reading %s" % sys.argv[1]
    pdict = ReadPuzzles(sys.argv[1])
    print "Found %d puzzles in the data file %s" % \
          (sum(len(val) for val in pdict.values()), sys.argv[1])

    # Create Code String
    print "Generating Code..."
    pstring = MakePyString(pdict)

    # Write code out to file
    print "Writing code to %s" % sys.argv[2]
    fhandle = open(sys.argv[2], 'wb')
    fhandle.write(pstring)
    fhandle.close()

    print "Finished!"
